/**********************************************************
 * AccountingManagerAction.java
 * Created by ankur
 * Last modified Date: Aug 5, 2008 11:36:37 AM by ankur
 * Version : 0.1
 * Copyright (c) 2008 - 2008 cyberThink Infotech Pvt. Ltd., All rights reserved.
 **********************************************************/

package com.printeverywhere.action;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.hibernate.HibernateException;

import com.opensymphony.xwork2.ActionContext;
import com.printeverywhere.delegator.CommonFunctionDelegator;
import com.printeverywhere.delegator.CreditCardServiceDelegator;
import com.printeverywhere.delegator.CreditCardTypeServiceDelegator;
import com.printeverywhere.delegator.GeneralOptionsServiceDelegator;
import com.printeverywhere.delegator.PromotionalCodesServiceDelegator;
import com.printeverywhere.delegator.UserServiceDelegator;
import com.printeverywhere.dto.AffiliateSettings;
import com.printeverywhere.dto.CreditCardType;
import com.printeverywhere.dto.Creditcard;
import com.printeverywhere.dto.GeneralOptions;
import com.printeverywhere.dto.MailingSystem;
import com.printeverywhere.dto.PromotionalCode;
import com.printeverywhere.dto.User;
import com.printeverywhere.dto.UserAffiliation;
import com.printeverywhere.dto.UsersInfo;
import com.printeverywhere.util.AdminConstants;
import com.printeverywhere.util.AttributeConstants;
import com.printeverywhere.util.CommonUtil;
import com.printeverywhere.util.DateUtil;
import com.printeverywhere.util.MailHelper;
import com.printeverywhere.util.SearchCriteria;
import com.printeverywhere.util.SessionUtil;

/**
 * The Class AccountingManagerAction.
 */
public class CreditCardAction extends FrontBaseSupport implements
		ServletRequestAware {

	public CreditCardAction() {
		super(true, false);
		setMyAccount(true);
	}

	/** Logger for this class. */
	private static final Logger logger = Logger
			.getLogger(CreditCardAction.class);
	private SearchCriteria searchCriteria = new SearchCriteria();
	private List<Creditcard> creditCardValueList = new ArrayList<Creditcard>();
	
	private String action;
	
	private GeneralOptions generalOptions;
	
	/** The referal. */
	private String referal;
	
	private PromotionalCode codeData;
	
	public String getReferal() {
		return referal;
	}

	public void setReferal(String referal) {
		this.referal = referal;
	}

	public PromotionalCode getCodeData() {
		return codeData;
	}

	public void setCodeData(PromotionalCode codeData) {
		this.codeData = codeData;
	}

	public void getCreditDataList() {
		try{
 		user = SessionUtil.getUser(request);
		if(creditCardTypeList.size() > 0){
			creditCardTypeList.clear();
		}
		if(creditCardValueList.size() > 0){
			creditCardValueList.clear();
		}
		if(creditCardTypeList.size() > 0){
			creditCardList.clear();
		}

		searchCriteria.removeAllAttribute();
		searchCriteria.setAsc(true);
		searchCriteria.setOrderBy(AdminConstants.TYPE);
		creditCardTypeList = CreditCardTypeServiceDelegator.getList(searchCriteria);

		searchCriteria.removeAllAttribute();
		searchCriteria.setAttribute(AttributeConstants.USER, SessionUtil
				.getUser(request));
		creditCardValueList = CreditCardServiceDelegator.getList(searchCriteria);
		for (Iterator<Creditcard> iterator = creditCardValueList.iterator(); iterator.hasNext();) {
			Creditcard type = (Creditcard) iterator.next();
			String creditCardNumber = type.getCardNumber();
			String cardNumber = type.getCardNumber().toString().substring(creditCardNumber.length() - 4, creditCardNumber.length());
			type.setNameOnCard(type.getNameOnCard()+", " + user.getUserId()+", ****-**********-*"+cardNumber + ", Exp. " + type.getExMonth() +"/"+ type.getExYear());
			creditCardList.add(type);
		}
		}catch (Exception e) {

		}
	}

	/**
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 */
	public String execute() throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("execute() - start");
		}
		try{
			getCreditDataList();
		}catch (Exception e) {

		}
		if (logger.isDebugEnabled()) {
			logger.debug("execute() - end");
		}
		return SUCCESS;
	}

	/**
	 * Adds the credit card.
	 *
	 * @return the string
	 *
	 * @throws Exception
	 *             the exception
	 */
	public String addCreditCard() throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("addCreditCard() - start");
		}
		if(action != null && action.equalsIgnoreCase("fromReg")){
			setLeftAllowed(false);
		}
		try{
			getCreditDataList();
			if (creditcard != null && creditcard.getCreaditCardId() != null) {
				creditcard = CreditCardServiceDelegator.getCreditcard(
						this.creditcard.getCreaditCardId(), SessionUtil
								.getUser(request));
			}
		}catch (Exception e) {
			getCreditDataList();
			logger.error(e.getMessage());
			return INPUT;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("addCreditCard() - end");
		}

		return SUCCESS;
	}

	/**
	 * Delete credit card.
	 *
	 * @return the string
	 *
	 * @throws Exception
	 *             the exception
	 */
	public String deleteCreditCard() throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("deleteCreditCard() - start"); //$NON-NLS-1$
		}
		try {
			if(creditCardList.size() == 1){
				addActionMessage("Credit card information can not be removed. Please note, you must have at least one valid credit card on your file for automatic charges. If you have to remove this card, please add a new valid card on your file then try to remove this card again. Thank you");
			}else{
				searchCriteria.removeAllAttribute();
				searchCriteria.setAttribute(AttributeConstants.CREADITCARDID,
						defaultCardId);
				if(CreditCardServiceDelegator.getList(searchCriteria).size() >0 ){
					creditcard = CreditCardServiceDelegator.getList(searchCriteria)
							.get(AdminConstants.ZERO_NUMBER);
					CreditCardServiceDelegator.deleteCreditcard(creditcard);
					addActionMessage("Credit card deleted.");
				}
			}
		} catch (Exception e) {
			getCreditDataList();
			addActionError("Default credit card can not be deleted.".intern());
			logger.info("Error in deleting credit card..."+ e.getMessage());
		}
		if (logger.isDebugEnabled()) {
			logger.debug("deleteCreditCard() - end"); //$NON-NLS-1$
		}

		return SUCCESS;
	}

	/**
	 * Default credit card.
	 *
	 * @return the string
	 *
	 * @throws Exception
	 *             the exception
	 */
	public String defaultCreditCard() throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("defaultCreditCard() - start"); //$NON-NLS-1$
		}
		try{
			getCreditDataList();
			user = SessionUtil.getUser(request);
			user.setCreditcard(CreditCardServiceDelegator.getCreditcard(
					defaultCardId, user));
			UserServiceDelegator.updateUser(user);
			request.getSession().setAttribute(AttributeConstants.USER, user);
		}catch (HibernateException e) {
			addActionError("Please, Add creditcard.");
			return INPUT;
		}catch (Exception e) {
			getCreditDataList();
			addActionError("Cannot Make default creditcard.");
			return INPUT;
		}
		if (logger.isDebugEnabled()) {
			logger.debug("defaultCreditCard() - end"); //$NON-NLS-1$
		}

		return SUCCESS;
	}

	public String addCreditCardSubmit() throws Exception {
		try{
			
			if(action != null && action.equalsIgnoreCase("fromReg")){
				user = (User) ActionContext.getContext().getSession().get("newUser");
				User referal = user;
				if (this.referal != null && this.referal.trim().length() > 0) {
					referal = UserServiceDelegator.getUser(Integer.parseInt(CommonUtil.decrypt(this.referal)));
					user.setUser(referal);
				}
				generalOptions = GeneralOptionsServiceDelegator.getGeneralOptions();
				if (generalOptions.getAutoApproveNewUsers() == true) {
					UserServiceDelegator.insertUser(user);
					addActionMessage("Your registration has been successful. You can login Here");
				}else{
					MailingSystem mailingSystem = (MailingSystem) ActionContext.getContext().getApplication().get(AdminConstants.MAILING_OPTIONS);
					MailHelper mailHelper = new MailHelper(mailingSystem.getServerAddress(), mailingSystem.getServerUsername(), mailingSystem.getServerPassword());

					StringBuffer URL = new StringBuffer();
					URL.append(CommonUtil.getLocalBasePath(request));
					URL.append("/mail/registerationConfirmationMail.htm?id=").append(user.getUserId()).append("&pass=").append(user.getPassword()).append("&uname=").append(user.getFirstName()).append("%20").append(user.getLastName()).append("&link=").append(user.getActivationKey());

					String message = CommonUtil.getURLContent(URL.toString());
					mailHelper.sendMail(mailingSystem.getAccountsConfirmationEmail(), user.getEmail(), "Account Confirmation", message);
					UserServiceDelegator.insertUser(user);
					addActionMessage("Your registration has been successful; we have sent activation link to the email address given. Activate first and then login to account.");
				}
			
				UsersInfo usersInfo = new UsersInfo();
				usersInfo.setUser(user);
				CommonFunctionDelegator.generalInsertbyobj(usersInfo);
				
				if (this.referal != null && this.referal.trim().length() > 0) {
					AffiliateSettings affiliateSettings = (AffiliateSettings) ActionContext.getContext().getApplication().get(AdminConstants.AFFILIATE_PROGRAM);
					UserAffiliation userAffiliation = new UserAffiliation();
					userAffiliation.setUserByUserId(referal);
					userAffiliation.setUserByReferalUserId(user);
					userAffiliation.setIsPercentage(affiliateSettings.getIsPercentage());
					userAffiliation.setIsBonus(affiliateSettings.getIsBonus());
					userAffiliation.setStartDate(DateUtil.getTodaysDate());

					if (affiliateSettings.getIsPercentage()) {
						userAffiliation.setPercentageBonus(affiliateSettings.getBonusPercentage());
						userAffiliation.setChangePercentage(affiliateSettings.getPercentageChange());
						if (affiliateSettings.getPercentageValidTill() != 0) {
							userAffiliation.setEndDate(DateUtil.addDate(userAffiliation.getStartDate(), Calendar.MONTH, affiliateSettings.getPercentageValidTill()));
						}
						CommonFunctionDelegator.generalInsertbyobj(userAffiliation);
					}
					if (affiliateSettings.getIsBonus()) {
						if (affiliateSettings.getBonusValidTill() != 0) {
							userAffiliation.setBonusAvailable(affiliateSettings.getBonusAmount());
							userAffiliation.setEndDate(DateUtil.addDate(userAffiliation.getStartDate(), Calendar.MONTH, affiliateSettings.getBonusValidTill()));
							CommonFunctionDelegator.generalInsertbyobj(userAffiliation);
						}
						referal.setCurrentBalance(referal.getCurrentBalance() + affiliateSettings.getBonusAmount());
						UserServiceDelegator.updateUser(referal);
					}
				}
				codeData = PromotionalCodesServiceDelegator.getPromotionalCodeFromCode(user.getPromotionalCode());
				if(codeData != null) {
					PromotionalCode code = PromotionalCodesServiceDelegator.get(codeData.getId());
					code.setUser(user);
					PromotionalCodesServiceDelegator.update(code);
				}
			
			}else{
				user = SessionUtil.getUser(request);
			}
			
			creditcard.setUser(user);
			Date date = DateUtil.getTodaysDate();
			String d = DateUtil.getTodaysDate().toString();
			int year = Integer.valueOf(d.substring(d.length()-4, d.length()));
			if(creditcard.getExMonth() < date.getMonth()){
				if(creditcard.getExYear().intValue() <= year  ){
					getCreditDataList();
					addActionError("Enter Proper Expiration year, Expiration month.");
					return INPUT;
				}
			}
			CreditCardServiceDelegator.insertCreditcard(creditcard);
			addActionMessage("Congratulations, the Credit Card you entered added to your account.".intern());
		}catch (Exception e) {
			user = SessionUtil.getUser(request);
			searchCriteria.removeAllAttribute();
			searchCriteria.setAsc(true);
			searchCriteria.setOrderBy(AdminConstants.TYPE);
			creditCardTypeList = CreditCardTypeServiceDelegator.getList(searchCriteria);
			addActionError("Sorry, creditcard Not Added, try again later.");
			logger.error(e.getMessage());
			logger.error(" ---> " + e.toString());
			return INPUT;
		}
		if(action != null && action.equalsIgnoreCase("fromReg")){
			if(ActionContext.getContext().getSession().get("newUser") != null){
				ActionContext.getContext().getSession().put("newUser", null);
			}
			setLoginPage(true);
			return "forwardLogin";
		}else{
			return SUCCESS;
		}
	}

	@Override
	public void validate() {
		user = SessionUtil.getUser(request);
		searchCriteria.removeAllAttribute();
		searchCriteria.setAsc(true);
		searchCriteria.setOrderBy(AdminConstants.TYPE);
		creditCardTypeList = CreditCardTypeServiceDelegator.getList(searchCriteria);
		if(creditcard.getCardNumber().length()>0){
			Pattern regEx = null;
			CreditCardType creditCardType =  CreditCardTypeServiceDelegator.getCreditCardType(creditcard.getCreditCardType().getId());
			if(creditCardType.getType().equalsIgnoreCase(AdminConstants.VISA)){
				regEx = Pattern.compile("^4\\d{3}-?\\d{4}-?\\d{4}-?\\d{4}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.AMEX)){
				regEx = Pattern.compile("^3[4,7]\\d{13}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.MASTERCARD)){
				regEx = Pattern.compile("^5[1-5]\\d{2}-?\\d{4}-?\\d{4}-?\\d{4}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.DINERS_CLUB)){
				regEx = Pattern.compile("^3[0,6,8]\\d{12}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.DISCOVER)){
				regEx = Pattern.compile("^6011-?\\d{4}-?\\d{4}-?\\d{4}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.ENROUTE_CARD)){
				regEx = Pattern.compile("^(2014|2149)\\d{11}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.JCB_CARD)){
				regEx = Pattern.compile("^(3[0-9]{4}|2131|1800)[0-9]{11}$");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.SOLO)){
				regEx = Pattern.compile("(^(6334)[5-9](\\d{11}$|\\d{13,14}$))|(^(6767)(\\d{12}$|\\d{14,15}$))");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.SWITCH)){
				regEx = Pattern.compile("((^(4911|4905|4903|4936|6333|6767)(\\d{12}$|\\d{14,15}$))|(^(633110|564182)(\\d{10}$|\\d{12,13}$)))");
			}else if(creditCardType.getType().equalsIgnoreCase(AdminConstants.BANK_CARD)){
				regEx = Pattern.compile("((^(5610)(\\d{12}$))|(^(560221|560225)(\\d{10}$)))");
			}
			int length = creditcard.getCvn().toString().length();
			if(((length < 3)||(length >4)) && (creditcard.getCvn()!= 0)){
				getCreditDataList();
				addActionError("Card verification number should be 3 to 4 digit long.");
			}
			length = creditcard.getIssueNumber().toString().length();
			if(((length < 2)||(length > 3)) && (creditcard.getIssueNumber() != 0)){
				getCreditDataList();
				addActionError("Issue number should be 2 to 3 digit long.");
			}
			Matcher fit = regEx.matcher(creditcard.getCardNumber());
			if(!fit.matches()){
				getCreditDataList();
				addActionError("Please, Enter valid credit card number.");
			}
		}
	}
	public static void main(String[] args) {
//		Pattern amexRegEx = Pattern.compile("((^(4911|4905|4903|4936|6333|6767)(\\d{12}$|\\d{14,15}$)) |(^(633110|564182)(\\d{10}$|\\d{12,13}$)))");

		//Pattern amexRegEx = Pattern.compile("((^(5610)(\\d{12}$))|(^(560221|560225)(\\d{10}$)))");
		Pattern amexRegEx = Pattern.compile("^[0-9_.]+[0-9a-zA-Z]*$");
                Matcher fit = amexRegEx.matcher("_99999jkhkjh");
                if (fit.matches()) {
                        System.out.println (" done");
                } else {
                	System.out.println (" not done");
                }
	}
	private HttpServletRequest request;

	private Creditcard creditcard;
	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	private List<Creditcard> creditCardList = new ArrayList<Creditcard>();
	private List<CreditCardType> creditCardTypeList = new ArrayList<CreditCardType>();
	private String button;
	private User user;
	private int defaultCardId;

	/**
	 * @return the defaultCardId
	 */
	public int getDefaultCardId() {
		return defaultCardId;
	}

	/**
	 * @param defaultCardId
	 *            the defaultCardId to set
	 */
	public void setDefaultCardId(int defaultCardId) {
		this.defaultCardId = defaultCardId;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	/**
	 * @param user
	 *            the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}

	/**
	 * @return the button
	 */
	public String getButton() {
		return button;
	}

	/**
	 * @param button
	 *            the button to set
	 */
	public void setButton(String button) {
		this.button = button;
	}

	/**
	 * @return the creditCardTypeList
	 */
	public List<CreditCardType> getCreditCardTypeList() {
		return creditCardTypeList;
	}

	/**
	 * @param creditCardTypeList
	 *            the creditCardTypeList to set
	 */
	public void setCreditCardTypeList(List<CreditCardType> creditCardTypeList) {
		this.creditCardTypeList = creditCardTypeList;
	}

	/**
	 * @return the creditcard
	 */
	public Creditcard getCreditcard() {
		return creditcard;
	}

	/**
	 * @param creditcard
	 *            the creditcard to set
	 */
	public void setCreditcard(Creditcard creditcard) {
		this.creditcard = creditcard;
	}

	// @Override
	public void setServletRequest(HttpServletRequest arg0) {
		request = arg0;

	}

	/**
	 * @return the creditCardList
	 */
	public List<Creditcard> getCreditCardList() {
		return creditCardList;
	}

	/**
	 * @param creditCardList
	 *            the creditCardList to set
	 */
	public void setCreditCardList(List<Creditcard> creditCardList) {
		this.creditCardList = creditCardList;
	}

	public String getAction() {
		return action;
	}

	public void setAction(String action) {
		this.action = action;
	}

	public GeneralOptions getGeneralOptions() {
		return generalOptions;
	}

	public void setGeneralOptions(GeneralOptions generalOptions) {
		this.generalOptions = generalOptions;
	}

}